﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#pragma once

#include <ui_SelectGColorDlg.h>
#include "IGraphicsStylePage.h"
#include <QTableWidget>
#include <QComboBox>
#include "ElementId.h"
#include "Color.h"
#include "IUiView.h"
#include "IUiDocument.h"
#include "WeakPtr.h"

typedef UInt64 WndId;
namespace gcmp
{
    class IDocument;
    class IModelView;
    class IGraphicsStyle;
    class VisibilityGraphics;
    class UniIdentity;
}

struct LineStyle
{
    double lineWidth;
    gcmp::Color lineColor;
    bool hasColorOverride;
    std::wstring lineType;
    double oldLineWidth;
    gcmp::Color oldLineColor;
    std::wstring oldLineType;

public:
    LineStyle();

};

class FaceHatchData
{
public:
    FaceHatchData()
        : m_projectionColor(gcmp::Color::Black)
        , m_projectionPattern(L"")
        , m_projectionAngle(0)
        , m_projectionScale(1)
        , m_isProjectionPatternOverride(false)
        , m_sectionColor(gcmp::Color::Black)
        , m_sectionPattern(L"")
        , m_sectionAngle(0)
        , m_sectionScale(1)
        , m_isSectionPatternOverride(false)
        , m_isProjectionColorOverride(false)
    {
    }

    void GetDataFrom(const gcmp::IGraphicsStyle& gstyleElemet, const gcmp::IModelView* pModelView = nullptr);
    void SetDataTo(gcmp::IGraphicsStyle& gstyleElement, gcmp::IModelView* pModelView = nullptr) const;

public:
    gcmp::Color     m_projectionColor;
    std::wstring    m_projectionPattern;
    double          m_projectionAngle;
    double          m_projectionScale;
    bool            m_isProjectionPatternOverride;
    gcmp::Color     m_sectionColor;
    std::wstring    m_sectionPattern;
    double          m_sectionAngle;
    double          m_sectionScale;
    bool            m_isSectionPatternOverride;
    bool            m_isProjectionColorOverride;
};

class SelectGColorDlg: public QDialog
{
    Q_OBJECT

public:

    SelectGColorDlg( const QColor& color,  QPushButton* bnt,QWidget *parent = 0);

    bool IsNoOverride()const{return noOverride;};

    QColor GetResultColor()const {return m_resColor;}

private slots:

    bool SelectNoOverride();

    bool SelectColor();
private:

    Ui::SelectColorDlg m_ui;

    bool noOverride;

    QPushButton* colorShowing;

    QColor qcolor;

    QColor m_resColor;
};

//TODO: 目前这个类依赖ProductConfig中的设置，后续需要去掉
class GraphicsStyleTable : public QWidget, public IGraphicsStylePage
{
    Q_OBJECT
public:
    GraphicsStyleTable(gcmp::IUiDocument * pUIDoc, gcmp::IUiView * currentView, 
        QDialog * parent, const std::vector<gcmp::UniIdentity>& usedCategories,
        const std::wstring& label = L"");

public:
    virtual QWidget* GetWidgetFW() override { return m_table; }
    virtual std::wstring GetLabel() const override { return m_label; }

public:
    virtual void OnApplied() override;
    virtual void RecordMaterialDatas() override;

private:
    friend class DrawLineStyleDelegate;
    std::map<int, LineStyle> GetLineStyleMap() const { return m_cellIndexLineStyleMap; }

private slots:
    void OnClickCell(int bnt);
    void OnClickCell_faceStyle(int bnt);
    void OnClickCell(int row, int column);
    void OnClickLineTypeCell(int iButtonIndex);
    void OnMaterialComboBox_currentIndexChanged(int index);

private:
    bool IsViewGraphicsStyle() const { return m_wpCurrentView.Get() != nullptr; }
    gcmp::IModelView* GetModelView() const;

    // 在Table里添加可见性checkbox
    void AddVisibilityCtrlToTable(QTableWidget* pTable, const gcmp::IModelView* pModelView, const gcmp::UniIdentity& uid, int row, int col);
    
    // 仅供日志录制使用
    void RecordMaterialCommand(const std::wstring& cmdName, gcmp::ElementId materialId, const gcmp::UniIdentity& categoryUniIdentity);

    // 初始化某一行的材质单元格
    void InitMaterialCell(const gcmp::IDocument* pDoc, int categoryIndex, const gcmp::UniIdentity& categoryUid, const gcmp::IGraphicsStyle* pGStyleElement);

    // 计算出材质下拉列表中可见的内容
    std::vector<std::wstring> CalcItemNames_inMaterialComboBox();

    // 某一个类别新增了一个材质，所有的下拉列表都需更新
    void UpdateComboBoxs_4_materialAdded(int categoryIndex, const std::wstring& materialName);

    // 更新材质的修改到doc
    void UpdateMaterialChanges_to_doc();

    // 获取指定类别是否允许设置材质
    bool CanCategoryHaveGraphicsMaterial(const gcmp::IDocument* pDocument, const gcmp::UniIdentity& categoryUid) const;

private:
    std::wstring m_label;
    QDialog* m_parent;

    static const int ms_visibilityGraphicsCount = 2;

    std::vector<gcmp::UniIdentity>  m_categories;
    gcmp::WeakPtr<gcmp::IUiView> m_wpCurrentView;
    gcmp::WeakPtr<gcmp::IUiDocument> m_wpUIDoc;

    typedef std::pair<int, int> CellType;

    QTableWidget* m_table;
    gcmp::OwnerPtr<QButtonGroup> m_opColorBtnGroup;      // 颜色按钮组
    gcmp::OwnerPtr<QButtonGroup> m_opLineTypeBtnGroup;   // 线型按钮组。
    std::map<CellType, QColor> m_colorMap;               // 颜色映射
    std::map<CellType, double> m_transparencyMap;        // 透明度映射
    std::map<int, LineStyle>    m_cellIndexLineStyleMap; // 线型映射
    std::vector<bool>   m_isFaceColorOverride;           // 面颜色是否覆盖 
    std::vector<bool>   m_isSectionFaceColorOverride;    // 截面颜色是否覆盖 

    // 材质相关
    std::vector<gcmp::ElementId> m_materialIds;       // 记录所有材质element
    std::map<gcmp::ElementId, gcmp::ElementId> m_materialChangeData; // 材质所做的修改<material element id（旧）, material element id（新）>
    std::vector<QComboBox*> m_materialComboBoxList;

    // 面样式相关
    std::vector<QColor> m_faceColor;                     // 面颜色
    std::vector<QColor> m_sectionFaceColor;              // 截面颜色
    std::vector<FaceHatchData>  m_faceHatchData;         // 面填充
    gcmp::OwnerPtr<QButtonGroup> m_opFaceStyleBtnGroup;
    std::map<WndId, int> m_buttonRowMap; // 记录了按钮在哪一行
};
